package net.jonbuck.tassoo.ui.dialog;

import net.jonbuck.tassoo.model.Attachment;
import net.jonbuck.tassoo.persistence.dao.TassooDao;
import net.jonbuck.tassoo.persistence.dao.TassooDaoImpl;
import net.jonbuck.tassoo.persistence.dao.util.TassooDaoHelperUtil;
import net.jonbuck.tassoo.ui.nl.Messages;
import net.jonbuck.tassoo.ui.util.CommonImages;

import org.apache.commons.lang.StringUtils;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.ValidationStatusProvider;
import org.eclipse.core.databinding.beans.BeanProperties;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.databinding.validation.IValidator;
import org.eclipse.core.databinding.validation.ValidationStatus;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.databinding.dialog.TitleAreaDialogSupport;
import org.eclipse.jface.databinding.dialog.ValidationMessageProvider;
import org.eclipse.jface.databinding.swt.WidgetProperties;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

/**
 * 
 * 
 * @since 1.0.0
 */
public class AttachmentDialog extends TitleAreaDialog {

	/** ... TODO Javadoc ... */
	private Attachment attachment;

	/** ... TODO Javadoc ... */
	private DataBindingContext bindingContext = new DataBindingContext();

	/** ... TODO Javadoc ... */
	private Text locationText;

	/** ... TODO Javadoc ... */
	private String message;

	/** ... TODO Javadoc ... */
	private TassooDao tassooDao = TassooDaoImpl.getInstance();

	/** ... TODO Javadoc ... */
	private String title;

	/** ... TODO Javadoc ... */
	private Text labelText;

	private Combo typeCombo;

	/**
	 * 
	 * @param parentShell
	 * @param attachmentTypes
	 * @param title
	 * @param message
	 */
	public AttachmentDialog(Shell parentShell, Attachment attachment, String title, String message) {
		super(parentShell);
		this.attachment = attachment;
		this.title = title;
		this.message = message;
	}

	/**
	 * 
	 */
	public void create() {
		super.create();
		setTitle(title);
		setMessage(message);
		setTitleImage(CommonImages.getImage(CommonImages.WIZBAN_ATTACHMENT));
	}

	/**
	 * 
	 */
	protected Control createDialogArea(Composite parent) {
		final Composite outerContainer = (Composite) super.createDialogArea(parent);

		Composite container = new Composite(outerContainer, SWT.NONE);
		GridLayout containerLayout = new GridLayout(3, false);
		containerLayout.marginTop = containerLayout.marginBottom = containerLayout.marginLeft = containerLayout.marginRight = 15;
		containerLayout.verticalSpacing = 15;
		container.setLayout(containerLayout);
		container.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

		initializeDialogUnits(container);

		Label lblType = new Label(container, SWT.NONE);
		lblType.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
		lblType.setText("Type:");

		typeCombo = new Combo(container, SWT.READ_ONLY);
		typeCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
		String[] typesList = TassooDaoHelperUtil.createTypeList(tassooDao);
		typeCombo.setItems(typesList);

		Label lblLabel = new Label(container, SWT.NONE);
		lblLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
		lblLabel.setText("Label:");

		labelText = new Text(container, SWT.BORDER);
		labelText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));

		Label lblLocation = new Label(container, SWT.NONE);
		lblLocation.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
		lblLocation.setText("Location:");

		locationText = new Text(container, SWT.BORDER);
		locationText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));

		Button btnBrowse = new Button(container, SWT.NONE);
		GridData gd_btnBrowse = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
		gd_btnBrowse.widthHint = 80;
		btnBrowse.setLayoutData(gd_btnBrowse);
		btnBrowse.setText("Browse");
		btnBrowse.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				FileDialog fileDialog = new FileDialog(Display.getCurrent().getActiveShell());
				String selectedFile = fileDialog.open();
				if (StringUtils.isNotBlank(selectedFile)) {
					locationText.setText(selectedFile);
				}
			}
		});

		// Build the separator line
		Label titleBarSeparator = new Label(parent, SWT.HORIZONTAL | SWT.SEPARATOR);
		titleBarSeparator.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

		initBindingSupport();
		initDataBindings();

		return container;
	}

	/**
	 * @return the attachment
	 */
	public Attachment getAttachment() {
		return attachment;
	}

	/**
	 * <p>
	 * <b>Initialises the binding support for the dialog.</b><br/>
	 * This method initialises a <code>TitleAreaDialogSupport</code> class which
	 * links an errors that are created from the data binding code to error
	 * messages that are displayed in the title area of the dialog. In order to
	 * manage the enablement of the OK button we need to subclass the validation
	 * message provider so that we can add code that either enables or disables
	 * the button based on whether there are any errors.
	 * </p>
	 */
	private void initBindingSupport() {
		TitleAreaDialogSupport tads = TitleAreaDialogSupport.create(this, bindingContext);
		tads.setValidationMessageProvider(new ValidationMessageProvider() {
			public String getMessage(ValidationStatusProvider statusProvider) {
				if (statusProvider == null) {
					return message;
				}
				return super.getMessage(statusProvider);
			}

			public int getMessageType(ValidationStatusProvider statusProvider) {
				int type = super.getMessageType(statusProvider);
				if (getButton(IDialogConstants.OK_ID) != null) {
					getButton(IDialogConstants.OK_ID).setEnabled(type == IMessageProvider.NONE);
				}
				return type;
			}
		});
	}

	/**
	 * <p>
	 * <b>Creates the data bindings for the form along with the field
	 * validators.
	 * </p>
	 * </b>
	 */
	private void initDataBindings() {
		IObservableValue typeObserveWidget = WidgetProperties.selection().observe(typeCombo);
		IObservableValue typeObserveValue = BeanProperties.value(Attachment.class, "type").observe(attachment);
		UpdateValueStrategy ttmTypeUpdateValueStrategy = new UpdateValueStrategy();
		ttmTypeUpdateValueStrategy.setBeforeSetValidator(new IValidator() {
			public IStatus validate(Object value) {
				String type = (String) value;
				if (StringUtils.isBlank(type)) {
					return ValidationStatus.info(Messages.attachmentdialog_error_notype);
				}
				return ValidationStatus.ok();
			}
		});
		bindingContext.bindValue(typeObserveWidget, typeObserveValue, ttmTypeUpdateValueStrategy, null);

		IObservableValue labelObserveWidget = WidgetProperties.text(SWT.Modify).observe(labelText);
		IObservableValue labelObserveValue = BeanProperties.value(Attachment.class, "label").observe(attachment);
		UpdateValueStrategy ttmLabelUpdateValueStrategy = new UpdateValueStrategy();
		ttmLabelUpdateValueStrategy.setBeforeSetValidator(new IValidator() {
			public IStatus validate(Object value) {
				String label = (String) value;
				if (StringUtils.isBlank(label)) {
					return ValidationStatus.info(Messages.attachmentdialog_error_nolabel);
				}
				return ValidationStatus.ok();
			}
		});
		bindingContext.bindValue(labelObserveWidget, labelObserveValue, ttmLabelUpdateValueStrategy, null);

		IObservableValue locationObserveWidget = WidgetProperties.text(SWT.Modify).observe(locationText);
		IObservableValue locationObserveValue = BeanProperties.value(Attachment.class, "location").observe(attachment);
		UpdateValueStrategy ttmLocationUpdateValueStrategy = new UpdateValueStrategy();
		ttmLocationUpdateValueStrategy.setBeforeSetValidator(new IValidator() {
			public IStatus validate(Object value) {
				String location = (String) value;
				if (StringUtils.isBlank(location)) {
					return ValidationStatus.info(Messages.attachmentdialog_error_nolocation);
				}
				return ValidationStatus.ok();
			}
		});
		bindingContext.bindValue(locationObserveWidget, locationObserveValue, ttmLocationUpdateValueStrategy, null);

	}

	/**
	 * @param attachment
	 *            the attachment to set
	 */
	public void setAttachment(Attachment attachment) {
		this.attachment = attachment;
	}

}
